package com.zys.http.processor;

import cn.hutool.json.JSONUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.zys.http.constant.HttpEnum;
import com.zys.http.entity.param.ParamProperty;
import com.zys.http.entity.velocity.MethodItem;
import com.zys.http.ui.tree.node.MethodNode;
import jdk.jfr.Description;
import org.jetbrains.annotations.NotNull;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author zhou ys
 * @since 2024-05-16
 */
public interface ApiProcessor {

    String NAME_KEY = "name";
    String VALUE_KEY = "value";
    String REQUEST_TYPE_KEY = "com.zys.ApiToolRequestType";
    @Description("@JsonProperty 全限名")
    String JSON_PROPERTY_ANNO_FQN = "com.fasterxml.jackson.annotation.JsonProperty";

    List<Object> EMPTY_ARRAY = Collections.emptyList();

    /**
     * 获取 Psi 元素所在的包
     *
     * @param psiElement psiClass 或 ktClass
     * @return 包名或 null
     */
    String packageName(PsiElement psiElement);

    // region Class 相关方法

    /**
     * 获取模块中的 controller
     *
     * @param module 模块
     * @return /
     */
    List<? extends PsiElement> controllers(Project project, Module module);

    /**
     * controller 上的路径
     *
     * @param psiElement psiClass/ktClass
     * @return /
     */
    String controllerPath(PsiElement psiElement);

    /**
     * controller 上的 swagger 说明
     *
     * @param psiElement psiClass/ktClass
     * @return /
     */
    String controllerSwagger(PsiElement psiElement);

    // endregion


    // region Method/Function 相关方法

    /**
     * controller 下的所有请求方法转换成树形结点
     *
     * @param psiElement     psiClass/ktClass
     * @param contextPath    模块路径
     * @return /
     */
    List<MethodNode> methodNodes(PsiElement psiElement, String contextPath);

    /**
     * 方法上的 swagger 说明
     *
     * @param psiElement PsiMethod/KtNameFunction
     * @return /
     */
    String methodSwagger(PsiElement psiElement);

    /**
     * 方法上的路径
     * @param element PsiMethod/KtNameFunction
     * @return /
     */
    String methodPath(PsiElement element);

    /**
     * 将方法参数转换成渲染模型
     *
     * @param element      PsiMethod/KtNameFunction
     * @param isJsonPretty 是否美化 json
     * @return /
     */
    Map<String, ParamProperty> methodParametersParse(@NotNull PsiElement element, boolean isJsonPretty);

    // endregion


    /**
     * 注解指定键的值
     *
     * @param psiElement PsiAnnotation/KtAnnotationEntry
     * @return /
     */
    String annotationValue(PsiElement psiElement, String[] attributeNames);

    List<MethodItem> postmanMethods(PsiElement psiElement, String contextPath);

    /**
     * 获取类型的默认值
     *
     * @param project /
     * @param type    PsiType/KtParameter
     * @return /
     */
    Object typeDefaultValue(Project project, Cloneable type);


    default void parameterParseResult(String parameterName, Object paramDefaultTypeValue, boolean isJson, boolean isJsonPretty, Map<String, ParamProperty> map, HttpEnum.ParamUsage paramUsage) {
        if (paramDefaultTypeValue instanceof Map<?, ?> paramMap) {
            if (isJson) {
                String jsonStr = isJsonPretty ? JSONUtil.toJsonPrettyStr(paramMap) : JSONUtil.toJsonStr(paramMap);
                map.put(REQUEST_TYPE_KEY, new ParamProperty(HttpEnum.ContentType.APPLICATION_JSON, HttpEnum.ParamUsage.HEADER));
                map.put(parameterName, new ParamProperty(jsonStr, HttpEnum.ParamUsage.BODY));
            } else {
                map.put(REQUEST_TYPE_KEY, new ParamProperty(HttpEnum.ContentType.APPLICATION_X_FORM_URLENCODED, HttpEnum.ParamUsage.HEADER));
                paramMap.forEach((k, v) -> map.put(k.toString(), new ParamProperty(v, HttpEnum.ParamUsage.URL)));
            }
        } else if (paramDefaultTypeValue instanceof Collection<?> || paramDefaultTypeValue instanceof Object[]) {
            if (isJson) {
                map.put(REQUEST_TYPE_KEY, new ParamProperty(HttpEnum.ContentType.APPLICATION_JSON, HttpEnum.ParamUsage.HEADER));
                String jsonStr = isJsonPretty ? JSONUtil.toJsonPrettyStr(paramDefaultTypeValue) : JSONUtil.toJsonStr(paramDefaultTypeValue);
                map.put(parameterName, new ParamProperty(jsonStr, HttpEnum.ParamUsage.BODY));
            } else {
                map.put(REQUEST_TYPE_KEY, new ParamProperty(HttpEnum.ContentType.APPLICATION_X_FORM_URLENCODED, HttpEnum.ParamUsage.HEADER));
                map.put(parameterName, new ParamProperty(paramDefaultTypeValue, paramUsage));
            }
        } else {
            if (isJson) {
                map.put(REQUEST_TYPE_KEY, new ParamProperty(HttpEnum.ContentType.APPLICATION_JSON, HttpEnum.ParamUsage.HEADER));
                map.put(parameterName, new ParamProperty(paramDefaultTypeValue, HttpEnum.ParamUsage.BODY));
            } else {
                map.put(REQUEST_TYPE_KEY, new ParamProperty(HttpEnum.ContentType.APPLICATION_X_FORM_URLENCODED, HttpEnum.ParamUsage.HEADER));
                map.put(parameterName, new ParamProperty(paramDefaultTypeValue, paramUsage));
            }
        }
    }
}
